﻿using System;
using System.Collections.Generic;
using System.Linq;

using Audit;
using AuditImitation.Graphics;
using BackOffice;
using DataLayer;

namespace AuditImitation
{
    public class AuditImitation
    {
        public int CountOfDaysForModelling { get; set; }
        public BackOffice.BackOffice BackOffice = new BackOffice.BackOffice();

        

        public GraphicsInfo StartImitation(DistributionsParameters distributionsParameters)
        {
            Resetdatabase();

            DistributionFacade.Instance.Init(distributionsParameters);

            var graphics = new GraphicsInfo();

            var materials = Repository.Instance.GetAllMaterials();

            graphics.AllMaterials = materials.Select(material => new GraphicInfoForMaterial(material)).ToList();

            const int countDaysInWeek = 7;

            CountOfDaysForModelling = DistributionFacade.Instance.GetCountOfDaysForModelling();

            for (int i = 1; i <= CountOfDaysForModelling; i++)
            {
                var currentDate = DateTime.Now.AddDays(i);
                var ordersForDay = new List<Order>();

                BackOffice.ProccessOrder(i);

                MaterialOrder todayDelivery = Repository.Instance.GetTodayDelivery(currentDate);
                if (todayDelivery != null)
                {
                    todayDelivery.Status = (byte) MaterialStatus.Delivered;
                    Repository.Instance.InsertDeliveryToStock(todayDelivery);
                }

                for (var j = 0; j < DistributionFacade.Instance.GetCountOfOrdersInDay(); j++)
                {
                    var order = ModellingOrderFacade.GetOrder(currentDate);

                    if (!order.ProductOrders.Any(item => item.Quantity > 0))
                    {
                        continue;
                    }

                    this.BackOffice.CalculateOrderCompletedDate(ref order, i);

                    switch (DistributionFacade.Instance.GetStatusOfOrder())
                    {
                        case 1:
                            order.IsUrgent = true;
                            break;
                        case 2:
                            order.IsDeleted = true;
                            break;
                    }

                    this.BackOffice.ApproveOrder(ref order, i);

                    if (!order.IsDeleted)
                    {
                        ordersForDay.Add(order);
                    }
                }

                var countOfChangedOrdersInDay = DistributionFacade.Instance.GetCountOfChangedOrdersInDay();
                countOfChangedOrdersInDay = countOfChangedOrdersInDay > ordersForDay.Count ? ordersForDay.Count : countOfChangedOrdersInDay;

                for (var j = 0; j < countOfChangedOrdersInDay; j++)
                {
                    var order = ordersForDay[j];

                    ModellingOrderFacade.ChangeOrder(currentDate, order);
                    this.BackOffice.CalculateOrderCompletedDate(ref order, i);

                    switch (DistributionFacade.Instance.GetStatusOfOrder())
                    {
                        case 1:
                            order.IsUrgent = true;
                            break;
                        case 2:
                            order.IsDeleted = true;
                            break;
                    }

                    this.BackOffice.ApproveOrder(ref order, i);
                }

                if (i % countDaysInWeek == 0 && i != 0)
                {
                    var statusOfDelivery = DistributionFacade.Instance.GetStatusOfChangeDeliveryMaterial();
                    var o = this.BackOffice.GetMaterialOrder(i);

                    if (o != null)
                    {

                        if (statusOfDelivery != 0)
                        {
                            o.ArrivalDate = o.ArrivalDate.AddDays(DistributionFacade.Instance.GetDelayDeliveryMaterial());
                            Repository.Instance.SubmitChanges();
                        }
                    }
                }

                foreach (var graphicInfoForMaterial in graphics.AllMaterials)
                {
                    var quantityOfMaterialInStock =
                        Repository.Instance.GetQuantityOfMaterialInStock(graphicInfoForMaterial.MaterialId);

                    graphicInfoForMaterial.CountsOfMaterial.Add(new ChartItem(i, quantityOfMaterialInStock));
                }
            }

            CreateOrdersGraphics(graphics);
            CreateDelaysGraphic(graphics);
            return graphics;
        }

        private void Resetdatabase()
        {
            Repository.Instance.DeleteTable();
            Repository.Instance.UpdateMaterials();
        }

        public void CreateOrdersGraphics(GraphicsInfo graphics)
        {
            for (int i = 0; i < CountOfDaysForModelling; i++)
            {
                var currentDate = DateTime.Now.AddDays(i);
                var countOfCompletedOrders = Repository.Instance.GetCountOfCompletedOrders(currentDate);
                var countOfDelayedOrders = Repository.Instance.GetCountOfDelayedOrders(currentDate);
                graphics.CompletedOrders.Add(new ChartItem(i, countOfCompletedOrders));
                graphics.DelayedOrders.Add(new ChartItem(i, countOfDelayedOrders));
            }
        }

        public void CreateDelaysGraphic(GraphicsInfo graphics)
        {
            const int lenOfWindow = 10;

            var delays = BackOffice.GetDaysDelays();

            var currentValue = delays.Take(lenOfWindow).Sum(x => x.Value);

            var currentDay = lenOfWindow;
            for (int i=currentDay; i <=delays.Keys.Count; i++)
            {
                graphics.Delays.Add(new ChartItem(i, currentValue));
                currentValue = delays.Skip(i-lenOfWindow).Take(lenOfWindow).Sum(item => item.Value);
            }
        }
    }
}
